package client.comm.commlib.utils

import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.provider.Settings
import android.util.Base64
import android.util.Log
import android.view.Window
import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
import androidx.core.content.FileProvider
import androidx.lifecycle.LifecycleOwner
import client.comm.commlib.ContextProvider
import client.comm.commlib.comm_ui.bean.Areas
import client.comm.commlib.comm_ui.bean.Image
import client.comm.commlib.dialog.UpdateVersionDialog
import com.forjrking.lubankt.Luban
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.MultiFormatWriter
import com.google.zxing.WriterException
import com.google.zxing.common.BitMatrix

import okhttp3.internal.and
import java.io.*
import java.security.InvalidKeyException
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import kotlin.collections.ArrayList

object Util {
    fun getSign(ts: String): String {
        val btl = "&OSpYVy#6g^Q7Fo#"
        val salt = ts + btl + "nx24Tej@R4gWVCopJkjHWjBo@n58LdQ5"
        val messageDigest: MessageDigest
        var encodestr: String? = ""
        try {
            messageDigest = MessageDigest.getInstance("SHA-256")
            messageDigest.update(salt.toByteArray(charset("UTF-8")))
            encodestr = byte2Hex(messageDigest.digest())
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        } catch (e: UnsupportedEncodingException) {
            e.printStackTrace()
        }
        return encodestr!!
    }


    fun getCaptchaSign(phone: String, time: String): String {
        val salt = time + phone + "nx24Tej@R4gWVCopJkjHWjBo@n58LdQ5"
        val messageDigest: MessageDigest
        var encodestr: String = ""
        try {
            messageDigest = MessageDigest.getInstance("SHA-256")
            messageDigest.update(salt.toByteArray(charset("UTF-8")))
            encodestr = byte2Hex(messageDigest.digest())
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        } catch (e: UnsupportedEncodingException) {
            e.printStackTrace()
        }
        return encodestr
    }

    fun genHMAC(data: String, key: String): String {
        var result: ByteArray? = null
        try {
            //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
            val signinKey =
                SecretKeySpec(key.toByteArray(charset("UTF-8")), "HmacSHA1")
            //生成一个指定 Mac 算法 的 Mac 对象
            val mac = Mac.getInstance("HmacSHA1")
            //用给定密钥初始化 Mac 对象
            mac.init(signinKey)
            //完成 Mac 操作
            val rawHmac = mac.doFinal(data.toByteArray(charset("UTF-8")))
            result = Base64.encode(rawHmac, Base64.DEFAULT)
        } catch (e: NoSuchAlgorithmException) {
            System.err.println(e.message)
        } catch (e: InvalidKeyException) {
            System.err.println(e.message)
        } catch (e: UnsupportedEncodingException) {
            System.err.println(e.message)
        }
        return if (null != result) {
            String(result).trim { it <= ' ' }
        } else {
            ""
        }
    }

    private fun byte2Hex(bytes: ByteArray): String {
        val stringBuffer = StringBuilder()
        var temp: String = ""
        for (i in bytes.indices) {
            temp = Integer.toHexString(bytes[i] and 0xFF)
            if (temp.length == 1) { //1得到一位的进行补0操作
                stringBuffer.append("0")
            }
            stringBuffer.append(temp)
        }
        return stringBuffer.toString()
    }

    fun checkOreoAndInstallApk() {
        ContextProvider.get().activity?.run {
            val saveFile =
                File(ContextProvider.get().apkPath)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val canInstall = packageManager.canRequestPackageInstalls()
                if (!canInstall) {
                    val builder =
                        AlertDialog.Builder(this)
                    builder
                        .setCancelable(false)
                        .setTitle("提示")
                        .setMessage("跳转授权安装应用权限?")
                        .setPositiveButton(
                            "确定"
                        ) { dialog, which ->
                            val packageURI =
                                Uri.parse("package:$packageName")
                            val intent = Intent(
                                Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
                                packageURI
                            )
                            startActivityForResult(
                                intent,
                                UpdateVersionDialog.GET_UNKNOWN_APP_SOURCES
                            )
                            dialog.dismiss()
                        }
                        .setNegativeButton(
                            "取消"
                        ) { dialog, which ->
                            finish()
                            dialog.dismiss()
                        }
                        .show()
                } else {
                    installAPK(this, saveFile)
                }
            } else {
                installAPK(this, saveFile)
            }
        }
    }

    fun installAPK(context: Context, saveFile: File?) {
        val anZintent = Intent(Intent.ACTION_VIEW)
        anZintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            anZintent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            anZintent.setDataAndType(
                FileProvider.getUriForFile(
                    context,
                    context.packageName + ".provider",
                    saveFile!!
                ), "application/vnd.android.package-archive"
            )
        } else anZintent.setDataAndType(
            Uri.fromFile(saveFile),
            "application/vnd.android.package-archive"
        )
        context.startActivity(anZintent)
    }

    fun hasInternet(): Boolean {
        val cm = ContextProvider.get().activity!!
            .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val info = cm.isDefaultNetworkActive
        return info
    }

    fun getStatusBarHeight(context: Context): Int {
        var result = 0;
        val resourceId =
            context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    fun setBg(res: Int, window: Window) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.apply {
                //添加关键标志位--状态栏和NavigationBar颜色设置的核心
                addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                //必须清除这个标志才能使设置的状态栏颜色生效
                clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
                //设置状态栏颜色
                statusBarColor = res
            }
        }
    }

    fun getExtension(filePath: String?): String {
        val options: BitmapFactory.Options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(filePath, options)
        val mimeType = options.outMimeType
        return mimeType.substring(mimeType.lastIndexOf("/") + 1)
    }

    fun copyFile(srcFile: File?, saveFile: String?, contentResolver: ContentResolver): Uri? {
        val uri: Uri?
        var inputStream: BufferedInputStream? = null
        var outputStream: BufferedOutputStream? = null
        try {
            inputStream = BufferedInputStream(FileInputStream(srcFile))
            val contentValues = ContentValues()
            contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, saveFile)
            contentValues.put(MediaStore.Images.Media.DESCRIPTION, saveFile)
            contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
            uri =
                contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
            outputStream = BufferedOutputStream(contentResolver.openOutputStream(uri!!))
            val buffer = ByteArray(1024 * 4)
            var len: Int
            while (inputStream.read(buffer).also { len = it } != -1) {
                outputStream.write(buffer, 0, len)
            }
            outputStream.flush()
        } catch (e: IOException) {
            e.printStackTrace()
            return null
        } finally {
            inputStream?.let {
                it.close()
            }
            outputStream?.let {
                it.close()
            }
        }
        return uri
    }

    fun getVersionCode(context: Context): Int {
        return try {
            context
                .packageManager
                .getPackageInfo(context.packageName, 0).versionCode
        } catch (ex: PackageManager.NameNotFoundException) {
            0
        }
    }

    fun toArray(images: List<Image>?): ArrayList<Uri>? {
        if (images == null) return null
        val len = images.size
        if (len == 0) return null
        val strings: ArrayList<Uri> = ArrayList<Uri>()
        var i = 0
        for (image in images) {
            image.imgUri?.let {
                strings.add(it)
            }
            i++
        }
        return strings
    }

    @Throws(WriterException::class)
    fun createQRCode(
        url: String, setWidth: Int,
        setHeight: Int
    ): Bitmap {
        val blackColor = -0x1000000
        val whiteColor = -0x1
        //生成二维矩阵,编码时指定大小,不要生成了图片以后再进行缩放,这样会模糊导致识别失败
        val hints: Hashtable<EncodeHintType, Any> = Hashtable<EncodeHintType, Any>()
        hints[EncodeHintType.CHARACTER_SET] = "utf-8"
        hints[EncodeHintType.MARGIN] = 0
        val matrix: BitMatrix =
            MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 400, 400, hints)
        val width: Int = matrix.getWidth()
        val height: Int = matrix.getHeight()

        // 二维矩阵转为一维像素数组,也就是一直横着排了
        val pixels = IntArray(width * height)
        for (y in 0 until height) {
            for (x in 0 until width) {
                if (matrix.get(x, y)) {
                    pixels[y * width + x] = blackColor
                } else pixels[y * width + x] = whiteColor
            }
        }
        val bitmap = Bitmap.createBitmap(
            width, height,
            Bitmap.Config.ARGB_8888
        )
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height)
        return bitmap
    }

    suspend fun getLuBan(lo: LifecycleOwner, uri: Uri): File {
        return Luban.with(lo)
            .load(uri)
            .ignoreBy(200)
            .get()
    }

    suspend fun getCityById(context: Context, id: String): Areas.City? {
        val input: InputStream = context.resources.assets.open("c_areas.json")
        val citys = input.listFromPath<Areas>()
        var city: Areas.City? = null
        citys?.let {
            for (v in it.RECORDS) {
                if (v.name.equals(id)) {
                    city = v
                    break
                }
            }
        }
        return city
    }
}